import org.lwjgl.*;
import org.lwjgl.opengl.*;
import org.lwjgl.opengl.Display;
import org.lwjgl.input.*;
import org.lwjgl.util.*;
import org.lwjgl.util.glu.*;

import com.bulletphysics.BulletStats;
import com.bulletphysics.collision.dispatch.CollisionObject;
import com.bulletphysics.collision.shapes.BoxShape;
import com.bulletphysics.collision.shapes.CollisionShape;
import com.bulletphysics.collision.shapes.ConcaveShape;
import com.bulletphysics.collision.shapes.ConvexShape;
import com.bulletphysics.collision.shapes.PolyhedralConvexShape;
import com.bulletphysics.collision.shapes.ShapeHull;
import com.bulletphysics.dynamics.DiscreteDynamicsWorld;
import com.bulletphysics.dynamics.RigidBody;
import com.bulletphysics.linearmath.CProfileIterator;
import com.bulletphysics.linearmath.CProfileManager;
import com.bulletphysics.linearmath.Clock;
import com.bulletphysics.linearmath.DefaultMotionState;
import com.bulletphysics.linearmath.Transform;
import com.bulletphysics.util.IntArrayList;
import com.bulletphysics.util.ObjectPool;


import java.awt.Font;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.List;
import java.util.BitSet;

import javax.vecmath.Color3f;
import javax.vecmath.Vector3f;
import java.util.Map;

import java.io.*;
import java.net.*;
import java.util.*;

import texture.*;
import java.util.StringTokenizer;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;

public class SSG extends BaseWindow{
	 
	  float posX = 0, posY = 0, posZ=0, rotX = 0, rotY = 0, scale = 1;
	  static int cursorX=0,cursorY=0;

	  RigidBody model;	//physics model which represent modelMD2
	  Frustum frustum;
	  BitSet facesDrawn;
	  static String mapName="Tutorial.bsp";
	  int camPosition=1;
	  //variables for physics
	  Physics physics_model;
	  static HashMap playerList = new HashMap();
	  private CProfileIterator profileIterator;
	  DiscreteDynamicsWorld dynamicsWorld;
	  private final Transform m = new Transform();
	  protected Clock clock = new Clock();
	  Vector3f temp = new Vector3f();
	  Thread bulletSound=new Sound("gunshot.wav",20);
	  long time = 0;
	  int fps=0;
	  static boolean messageBoolean=false;
	  static public int killAngle=0;
	  String cd="5";
	  static int messageTTL=5;
	  boolean isCountdown=false;
	  static public String playerHitID = "-1";
	  static public String playerHitByID = "-1";
	  static String message = "test";

	  //model MD2
	  int state = 0;	//state for animating object
	  static Player modelMD2;
	  Vector3f modelVelocity = new Vector3f();
	  int delay=0;
	  int countdown=10;
	  TrueTypeFont trueTypeFont;
	  String fpsPrint="";
	  static boolean multiplayer = false;
	  private static final int MAX_BULLET=20;
	  
	  boolean showStats = false;
	  int statsPosition = -40;
	  boolean renderStats = false;
	    
	  protected void execute()
		{
			try {
				initDisplay();
				
			} catch (LWJGLException e) {
				System.err.println("Can't open display.");
				System.exit(0);
			}
			setupView();
			initFont();
			Menu.showMenu(trueTypeFont);
			loadingScreen();
			BSP.LoadBSP(mapName);
			
			  
		    time=System.nanoTime()/1000000L;
			long start_time = System.nanoTime();
			BSP.lightMappingEnabled = true;
			BSP.CreateDisplayListFromBSP();
			System.out.println("Game loaded in "+((float)(System.nanoTime()-start_time)/1000000000)+" s.");
			
			BaseWindow.isRunning = true;
		
			//stuff for physics
			physics_model = BSP.get_physicModel();
			BulletStats.setProfileEnabled(true);
			profileIterator = CProfileManager.getIterator();
			dynamicsWorld = physics_model.getDynamicsWorld();	//get our dynamic world that we create when loading map in BSP
			
			frustum = new Frustum();
			facesDrawn = new BitSet();
			
			//loading MD2
			modelMD2 = new Player(setModelPosition());	//set right model position based on which map is chosen	
			modelMD2.modelName = "WalkMech.md2";
			modelMD2.LoadModelAndTextures("WalkMech.md2");	//load object	
			
			
			modelMD2.model = modelMD2.getPhyModel();	//load physics model, for later use

			new ClientNIO("192.168.1.107");
		
			mainLoop();
			Display.destroy();
			
		}	  
	 
	 /**
	 * Initial setup of projection of the scene onto screen, lights etc.
	 */	  
	  protected void setupView()
		{
		  
		  
		  GL11.glEnable(GL11.GL_BLEND); // Enabled blending
		  GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); // selects blending method
	      GL11.glEnable(GL11.GL_ALPHA_TEST); // allows alpha channels or transperancy
	      GL11.glAlphaFunc(GL11.GL_GREATER, 0.1f); // sets aplha function
		  // enable depth buffer (off by default)
		  GL11.glEnable(GL11.GL_DEPTH_TEST); 
		  // enable culling of back sides of polygons
	      GL11.glEnable(GL11.GL_CULL_FACE);
	      
	      GL11.glEnable(GL11.GL_TEXTURE_2D);
		  // mapping from normalized to window coordinates
		  GL11.glViewport(0, 0, 1024, 768);
		   
		  // setup projection matrix stack
		  GL11.glMatrixMode(GL11.GL_PROJECTION);
	      GL11.glLoadIdentity();
	      Mouse.setGrabbed(true);
	      // perspective projection (45% FOV, 4/3 aspect, clipping near 1, far 30);
	      GLU.gluPerspective(50, 1024 / (float)768, 10.0f, 40000.0f);
	 
	      // Camera view
	      GLU.gluLookAt(0, 0, 0,600,0, 0, 0, 1, 0);
	      setCameraMatrix();     
		}
	  
	  private void initFont(){
			Font font = TrueTypeFont.getFont("Computerfont", Font.PLAIN, 32);
			if (font == null) {
				System.out.println("Serif font.");
				font = new Font("Serif", Font.PLAIN, 40);
			}
			trueTypeFont = new TrueTypeFont(font, true);
	  }
	  
	  private void loadingScreen(){
		  set2DMode(); //switch to 2D mode for current resolution
		  // render Loading screen
		  trueTypeFont.drawString(370, trueTypeFont.getHeight()*10, "Loading Game ...", 1f,1f);
		  set3DMode();
		  Display.update();
	  }
	  
	  private void showStats(){
		  if(showStats && statsPosition < BaseWindow.width/2 -100)
			  statsPosition+=40;
		  else if(!showStats && statsPosition > -40)
			  statsPosition-=40;
		  if(statsPosition <= -40)
			  renderStats = false;
			  	  
		  //drawing stats
		  set2DMode();
		  trueTypeFont.drawString(statsPosition, trueTypeFont.getHeight()*11, "Stats", 1f,1f);
		  Iterator iterator = playerList.keySet().iterator();
		  int i=0;
		  trueTypeFont.drawString(statsPosition-100, trueTypeFont.getHeight()*10,"Player "+modelMD2.id+"           "+modelMD2.score+" kills", 1f,1f);
		  while( iterator.hasNext() ){
			 // System.out.println("test");
			  String playerID = (String)iterator.next();
			  Player player = (Player) playerList.get(playerID);
			  trueTypeFont.drawString(statsPosition-100, trueTypeFont.getHeight()*(9-i),"Player "+playerID+"    "+player.score+" kills", 1f,1f);
			  i++;
			}
		  set3DMode();			  
	  }

	  public void showString(){
		  set2DMode();
		  trueTypeFont.drawString(10, trueTypeFont.getHeight()*3,message, 1f,1f);
		  set3DMode();	  
	  }
	  
 	  private Vector3f setModelPosition(){
		  //int spawn=(int)(Math.random()*100);
 		  if(mapName.compareTo("Tutorial.bsp")==0){
			//  if(spawn <33)
			  return new Vector3f(0f,33f,0); 
		  }
		//	  if(spawn<66)
			//	  return new Vector3f(-597f, 221f, 809f);
			 // return new Vector3f(-2293f, -62f, -1422f);
		  //}
		  if(mapName.compareTo("cht3.bsp")==0){
			  return new Vector3f(500f,-150f,640f);
		  }
		  
		  return new Vector3f(0f,0f,0);
	  }
	  
	  protected void setCameraMatrix()
	  {
	    // model view stack 
	    GL11.glMatrixMode(GL11.GL_MODELVIEW);
	    GL11.glLoadIdentity();
	    // setup view space; 
	    // translate to 0,2,4 and rotate 30 degrees along x 
	    GL11.glTranslatef(0, 0f, 0f);
	    GL11.glRotatef(0.0f, 1.0f, 0.0f, 0.0f);    
	  }
	  
	  /**
	   * Resets the view of current frame
	   */
	  protected void resetView()
	  {
	    // clear color and depth buffer
	    GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
	  }
	  
	  // Renders the level => determine current leaf and cluster 
	 // then check visible cluster from current cluster
	  protected void renderLevel(float x, float y, float z) {
		  
		  facesDrawn.clear();
		  
		  int leafIndex = BSP.FindLeaf(x,y,z);
		  //System.out.println("leaf index is " + leafIndex);
		  int cluster = BSP.leaf[leafIndex].cluster;
		//  System.out.println("laef index is " + leafIndex + " cluster is " + cluster);
		  int i = BSP.numOfLeafs;
		  int visibleFaces = 0;
		 
		  while(i > 0) {
			  i--;
			 
			 // if(BSP.IsClusterVisible(cluster, BSP.leaf[i].cluster) == false) continue;
			 //  if(frustum.BoxInFrustum(BSP.leaf[i].mins[0], BSP.leaf[i].mins[1], BSP.leaf[i].mins[2],BSP.leaf[i].maxs[0], BSP.leaf[i].maxs[1], BSP.leaf[i].maxs[2]) == false) continue;
			 // System.out.println("i is " + i + " cluster is " + BSP.leaf[i].cluster);
			  int faceCount = BSP.leaf[i].n_leaffaces - 1;
			  
			  while(faceCount >= 0) {
				  int faceIndex = BSP.leafface[BSP.leaf[i].leafface + faceCount].cluster;
				  if(facesDrawn.get(faceIndex) == false) {
					  visibleFaces++;
					  facesDrawn.set(faceIndex);
					  GL11.glCallList(faceIndex); 
				  }
				  faceCount--;
			  }
			 
		  }
		  
		  
		  
	  }
		
	  public static void set2DMode() {
		  //GL11.glDisable(GL11.GL_DEPTH_TEST);
		  GL11.glMatrixMode(GL11.GL_PROJECTION);                        // Select The Projection Matrix
		  GL11.glPushMatrix();                                     // Store The Projection Matrix
		  GL11.glLoadIdentity();                                   // Reset The Projection Matrix
		  GL11.glOrtho(0, width, 0, height, -1, 1);                          // Set Up An Ortho Screen
		  GL11.glMatrixMode(GL11.GL_MODELVIEW);                         // Select The Modelview Matrix
		  GL11.glPushMatrix();                                     // Store The Modelview Matrix
		  GL11.glLoadIdentity();                                   // Reset The Modelview Matrix
	  }
	  
	  public static void set3DMode() {
		  GL11.glMatrixMode(GL11.GL_PROJECTION);                        // Select The Projection Matrix
		  GL11.glPopMatrix();                                      // Restore The Old Projection Matrix
		  GL11.glMatrixMode(GL11.GL_MODELVIEW);                         // Select The Modelview Matrix
		  GL11.glPopMatrix();                                      // Restore The Old Projection Matrix
		  //GL11.glEnable(GL11.GL_DEPTH_TEST);
	  }
	  /**
	   * Renders current frame
	   */
	  protected void renderFrame()
	  {  
		   
		  Iterator iterator = playerList.keySet().iterator();
			while( iterator. hasNext() ){
				String playerID = (String)iterator.next();
				Player player = (Player) playerList.get(playerID);

				if(player.loadedTextures == false) {
				//	System.out.println("loading textures for new model");
					player.LoadModelAndTextures(player.modelName);
					player.loadedTextures = true;
				}
			}
			
		  	GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_STENCIL_BUFFER_BIT);
		  
		    // model view stack 
		    GL11.glMatrixMode(GL11.GL_MODELVIEW);
		    
		    // save camera matrix
		    GL11.glPushMatrix();

		    
		    if(camPosition==1)
		    	GL11.glTranslatef(0.0f, -50.0f, .0f);	
		    if(camPosition==2)
		    	GL11.glTranslatef(200.0f, -50.0f, .0f);	//here we set camera distance from object
		    //GL11.glRotatef(90, 0, 1, 0);
		    GL11.glRotatef(cursorX, 0,1, 0);
		   
		    //GL11.glRotatef(-cursorY/10, 0,0, 1);   
			if(modelMD2.isKilled&&!isCountdown)
				deathAnimation(modelMD2);
			
		    modelMD2.m_rY=-cursorX;

		    
		    GL11.glTranslatef(-modelMD2.m_nX, -modelMD2.m_nY, -modelMD2.m_nZ);  	
		    
		    //FPS counter
		    fps++;
		    long now=System.nanoTime()/1000000L;
		    if (now-time>=1000) {
		        time=now;
		        fpsPrint = "FPS:"+fps;
		        fps=0;
		        modelMD2.spree++;
		        if(isCountdown)
		        	countdown();
		        if(messageBoolean){
		        	messageTTL--;
		        	if(messageTTL==0){
		        		messageBoolean=false;
		        		messageTTL=5;
		        	}
		        }
		     }		    	

		    set2DMode(); //switch to 2D mode
		    GL11.glTranslatef(0, -50, 0);
		    drawCursor();
		    GL11.glTranslatef(0, 50, 0);
		    // draw FPS to the screen
			trueTypeFont.drawString(10, trueTypeFont.getHeight()*14, fpsPrint, 1f,1f);
			//draw ammo
			trueTypeFont.drawString(10, trueTypeFont.getHeight()*2,"Ammo", 1f,1f);
			String ammo="";
			for(int i=0; i<MAX_BULLET-physics_model.noOfBullet(); i++)
				ammo+="|";
			trueTypeFont.drawString(10, trueTypeFont.getHeight(), ammo, 1f,1f);
			trueTypeFont.drawString(830, trueTypeFont.getHeight(),"Health:"+modelMD2.health, 1f,1f);
			if(messageBoolean)
				showString();
			if(isCountdown)
				trueTypeFont.drawString(BaseWindow.width/2-100, BaseWindow.height/2-200,cd , 8f,8f);

		    set3DMode();
		    
		    if(!isCountdown)
		    	renderPhysics();
		    frustum.CalculateFrustum();
		    renderLevel(-modelMD2.m_nX, -modelMD2.m_nY, -modelMD2.m_nZ);
		    if(renderStats)
		    	showStats();
		    
		    // discard current matrix 

		    GL11.glPopMatrix(); 
	    }
	  
	  protected void deathAnimation(Player player){
		  if(killAngle < 90) {
		    killAngle+=3;

		    player.m_rX=killAngle;

		  }else{
	    	if(player == modelMD2) 
	    		isCountdown=true; 

		  }
		  
	  }
	 
	  protected void countdown(){
		  int temp=Integer.parseInt(cd);
		  temp--;
		  System.out.println(temp);
		  cd=Integer.toString(temp);
		  if(temp==0){
			  modelMD2.isKilled=false;
			  isCountdown=false;
			  cd="5";	
			  Vector3f position = setModelPosition();
			  modelMD2.setPosition(position.x, position.y, position.z);
			  modelMD2.health=100;
			  modelMD2.respawned = true;

			  modelMD2.m_rX = 0;
			  killAngle = 0;

		  }
	  }
	  
	  protected static Vector3f getViewDirections(){
		  return new Vector3f(10000*(float)Math.cos(((cursorX%360)/(float)360*(2*Math.PI))),-500f,10000*(float)Math.sin(((cursorX%360)/(float)360*(2*Math.PI))));
 	  }
	  
	  protected void renderPhysics(){
		
		//get time for proper simulation

          dynamicsWorld.stepSimulation(1,4);
	   
		if (dynamicsWorld != null) {
			int numObjects = dynamicsWorld.getNumCollisionObjects();
			for (int i=0; i < numObjects; i++) {
				CollisionObject colObj = dynamicsWorld.getCollisionObjectArray().get(i);
				RigidBody body = RigidBody.upcast(colObj);

				if (body != null && body.getMotionState() != null) {
					DefaultMotionState myMotionState = (DefaultMotionState) body.getMotionState();
					m.set(myMotionState.graphicsWorldTrans);
				}
				else {
					colObj.getWorldTransform(m);
				}
				//start of drawing object or map
				{
					Transform trans = m;
					CollisionShape shape = colObj.getCollisionShape();
					
					
					ObjectPool <Transform> transformsPool = ObjectPool.get(Transform.class);
					ObjectPool <Vector3f> vectorsPool = ObjectPool.get(Vector3f.class);

/*					//translation with matrx - here we also get rotation
 					trans.getOpenGLMatrix(glMat);
					FloatBuffer buffer = ByteBuffer.allocateDirect(16*4).asFloatBuffer();
					buffer.put(glMat);
					buffer.rewind();
					GL11.glMultMatrix(buffer);*/
					
					boolean useWireframeFallback = false;
					switch (shape.getShapeType()) {
						case BOX_SHAPE_PROXYTYPE: {	//here we draw our model
							
							//if object is bullet
							if(physics_model.isBullet(colObj)){
																
								Transform t = new Transform();
								colObj.getWorldTransform(t);
								ObjectBullet.renderBullet(t.origin.x, t.origin.y, t.origin.z);
								String player_hitted = physics_model.didHitModel(t, body, shape); //check if bullet hit other model (player)
								if( player_hitted.equals("-1")==false){	//if there was hit, we have id of hit player
									numObjects--;
									System.out.println("Player ID:"+player_hitted);
									playerHitID = player_hitted;
									
								}else{ 
									if(physics_model.checkTTLBullet(body, shape))	//check if bullet has timeout, if it has, lower number of items in local counter
										numObjects--;
								}
								
							}else{
						
								Transform t = new Transform();
								

//								colObj.getWorldTransform(t);	//colObj is the same as modelMD2.model, because with switch we choose only box shapes
								modelMD2.model.getWorldTransform(t);

								modelMD2.setPosition(t.origin.x, t.origin.y, t.origin.z);
								modelMD2.renderObject(modelMD2.state);
								
								//check if player has fallen somewhere
								modelMD2.model.getLinearVelocity(modelVelocity);
								if(modelVelocity.y < -400){
									isCountdown = true;
									countdown();
								}
								
									
								
								
								Iterator iterator = playerList.keySet().iterator();
								while( iterator. hasNext() ){
									String playerID = (String)iterator.next();
									Player player = (Player) playerList.get(playerID);
									if(player.isKilled==true)
										deathAnimation(player);
									Transform t2 = new Transform();
									
									player.model.getWorldTransform(t2);
									player.setPosition(t2.origin.x, t2.origin.y, t2.origin.z);
									player.renderObject(player.state);
									
								
								}
								
								
								useWireframeFallback = false;
							}
							break;
							
						}
					}
					
					if (useWireframeFallback) {		//here we draw map in debug mode (only ConvexShape) to enable set useWireframeFallback
						// for polyhedral shapes
						if (shape.isPolyhedral()) {
							PolyhedralConvexShape polyshape = (PolyhedralConvexShape) shape;
							GL11.glBegin(GL11.GL_LINES);

							Vector3f a = vectorsPool.get(), b = vectorsPool.get();
							int k;
							for (k = 0; k < polyshape.getNumEdges(); k++) {
								polyshape.getEdge(k, a, b);

								GL11.glVertex3f(a.x, a.y, a.z);
								GL11.glVertex3f(b.x, b.y, b.z);
							}
							GL11.glEnd();
							
							vectorsPool.release(a);
							vectorsPool.release(b);
						}
					}
				}
			}
		}
	  }
	  
	  protected void drawCursor(){
		  
		  GL11.glBegin(GL11.GL_QUADS);
			
		  //vertical 
		  int width=Display.getDisplayMode().getWidth();
		  int height=Display.getDisplayMode().getHeight();
		  
		  
		  GL11.glVertex2f(width/2+15, height/2-1);
		  GL11.glVertex2f(width/2+15, height/2+1);
		  GL11.glVertex2f(width/2-15, height/2+1);
		  GL11.glVertex2f(width/2-15, height/2-1);
		  
		  GL11.glVertex2f(width/2+1, height/2-10);
		  GL11.glVertex2f(width/2+1, height/2+10);
		  GL11.glVertex2f(width/2-1, height/2+10);
		  GL11.glVertex2f(width/2-1, height/2-10);
		
		  
		  GL11.glEnd();
	  }
	  	  
  	  protected void processInput()
	  { 
  		if(Keyboard.isKeyDown(Keyboard.KEY_F2))
    		camPosition=2;
    	if(Keyboard.isKeyDown(Keyboard.KEY_F1))
    		camPosition=1;
    	if(Keyboard.isKeyDown(Keyboard.KEY_TAB)){
    		showStats = true;
    		renderStats = true;
    	}else if(!Keyboard.isKeyDown(Keyboard.KEY_TAB) && showStats){
    		showStats = false;
    	}
  		 if(!modelMD2.isKilled){
		    //mouse commands 
		    int mouseDX = Mouse.getDX();
	        int mouseDY = Mouse.getDY();
	        int mouseDW = Mouse.getDWheel();
	        // handle mouse motion
	        if (mouseDX != 0 || mouseDY != 0 || mouseDW != 0) {
	            cursorX += mouseDX;
	            cursorY += mouseDY;
	            if (cursorX < 0) {
	                cursorX = 0;
	            }
	            else if (cursorX > Display.getDisplayMode().getWidth()) {
	                cursorX = Display.getDisplayMode().getWidth();
	            }
	            if (cursorY < 0) {
	                cursorY = 0;
	            }
	            else if (cursorY > Display.getDisplayMode().getWidth()) {
	                cursorY = Display.getDisplayMode().getWidth();
	            }
	            //mouseMove(cursorX,cursorY);
	            //msg("DX=" + mouseDX + " DY=" + mouseDY + " cursorX=" + cursorX);
	        }
	        
	        if(Mouse.isButtonDown(0)){
	        	if(physics_model.noOfBullet() < MAX_BULLET){	// max number of bullets in map
	        		physics_model.addBullet(new Vector3f(modelMD2.m_nX, modelMD2.m_nY, modelMD2.m_nZ));
	        		
		        	try{
		        		if(bulletSound.getState().equals("RUNNABLE"))
		        			bulletSound.destroy();
		//        		bulletSound.setPriority(Thread.MIN_PRIORITY);
		        		bulletSound.start();
		        	}
		        	catch(IllegalThreadStateException e){
		        		//e.printStackTrace();
		        		bulletSound=new Sound("gunshot.wav",20);
		        	}
	        	}
	        }
		         
		  //model commands, every time key is pressed we activate model, because after some time jbullet doesnt check inactivated models for movement
	        if (Keyboard.isKeyDown(Keyboard.KEY_RIGHT)||Keyboard.isKeyDown(Keyboard.KEY_D)){

		    	modelMD2.model.activate();
		    	modelMD2.model.applyCentralImpulse(new Vector3f(new Vector3f(10000*(float)Math.cos((Math.PI/2+(cursorX%360)/(float)360*(2*Math.PI))),0f,10000*(float)Math.sin(Math.PI/2+(cursorX%360)/(float)360*(2*Math.PI)))));
		    	modelMD2.state=1;
		    }
		    if (Keyboard.isKeyDown(Keyboard.KEY_LEFT)||Keyboard.isKeyDown(Keyboard.KEY_A)){
		    	modelMD2.model.activate();
		    	modelMD2.model.applyCentralImpulse(new Vector3f(new Vector3f(-10000*(float)Math.cos((Math.PI/2+(cursorX%360)/(float)360*(2*Math.PI))),0f,-10000*(float)Math.sin(Math.PI/2+(cursorX%360)/(float)360*(2*Math.PI)))));
		    	modelMD2.state=1;
		    }
		    if (Keyboard.isKeyDown(Keyboard.KEY_SPACE) && physics_model.checkJump()){
		    	modelMD2.model.activate();
		    	modelMD2.model.applyCentralImpulse(new Vector3f(0f,7000f,0f));
		    }
		    if (Keyboard.isKeyDown(Keyboard.KEY_UP)||Keyboard.isKeyDown(Keyboard.KEY_W)){
		    	modelMD2.model.activate();
		    	modelMD2.model.applyCentralImpulse(new Vector3f(10000*(float)Math.cos(((cursorX%360)/(float)360*(2*Math.PI))),0f,10000*(float)Math.sin((cursorX%360)/(float)360*(2*Math.PI))));
		    	modelMD2.state=1;
		    }
		    if (Keyboard.isKeyDown(Keyboard.KEY_DOWN)||Keyboard.isKeyDown(Keyboard.KEY_S)){
		    	modelMD2.model.activate();
		    	modelMD2.model.applyCentralImpulse(new Vector3f(-10000*(float)Math.cos(((cursorX%360)/(float)360*(2*Math.PI))),0f,-10000*(float)Math.sin(((cursorX%360)/(float)360*(2*Math.PI))))); 
		    	modelMD2.state=2;
		    }
		  if(!Keyboard.isKeyDown(Keyboard.KEY_RIGHT) && !Keyboard.isKeyDown(Keyboard.KEY_LEFT) && !Keyboard.isKeyDown(Keyboard.KEY_SPACE)
				  && !Keyboard.isKeyDown(Keyboard.KEY_UP) && !Keyboard.isKeyDown(Keyboard.KEY_DOWN) && !Keyboard.isKeyDown(Keyboard.KEY_SPACE)) {
			  modelMD2.state = 0;
		  }
  		 }
	    super.processInput();
	    
	  }
	  
 	  public static void setMapName(String map){
 		  mapName = map;
 	  }
 	  
	  public static void main(String[] args) {
		 
		  (new SSG()).execute();
		 
	  }

	}
